#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
结果合并与冲突处理模块
负责合并视觉分析结果和文本补充分析结果，并处理可能的冲突情况

T3-05子任务：结果合并与冲突处理
输入：视觉分析结果、文本补充分析结果
输出：合并后的统一结果，包含冲突处理标记
"""

import json
import logging
from typing import Dict, Any, List, Tuple, Optional
from datetime import datetime
import copy

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
)
logger = logging.getLogger(__name__)


class ResultMerger:
    """
    结果合并器
    提供视觉分析结果和文本补充分析结果的合并功能，以及冲突检测和处理
    """
    
    def __init__(self):
        """
        初始化结果合并器
        """
        # 冲突处理策略
        self.conflict_resolution_strategies = {
            "confidence_based": self._resolve_by_confidence,  # 基于置信度
            "source_priority": self._resolve_by_source_priority,  # 基于来源优先级
            "log_only": self._resolve_by_logging  # 只记录，保留原始值
        }
        
        # 默认策略
        self.default_strategy = "confidence_based"
        
        # 来源优先级（数字越小，优先级越高）
        self.source_priorities = {
            "manual": 1,       # 人工标注（最高优先级）
            "text_supplement": 2,  # 文本补充分析
            "vision": 3        # 视觉分析（默认）
        }
        
        # 配置阈值
        self.confidence_thresholds = {
            "high": 85,    # 高置信度阈值
            "medium": 70,  # 中等置信度阈值
            "low": 50      # 低置信度阈值
        }
        
        logger.info("ResultMerger初始化完成")
    
    def merge_results(self, 
                     vision_result: Dict[str, Any], 
                     supplement_result: Dict[str, Any],
                     strategy: str = None) -> Dict[str, Any]:
        """
        合并视觉分析结果和文本补充分析结果
        
        Args:
            vision_result: 视觉分析结果
            supplement_result: 文本补充分析结果
            strategy: 冲突处理策略名称，可选值: confidence_based, source_priority, log_only
                      如果未指定，使用默认策略
        
        Returns:
            Dict[str, Any]: 合并后的结果
        """
        try:
            # 创建深拷贝避免修改原始数据
            merged_result = copy.deepcopy(vision_result)
            
            # 确保必要的字段存在
            if "encoding_categories" not in merged_result:
                merged_result["encoding_categories"] = {}
            
            # 添加合并元数据
            merged_result["merger_info"] = {
                "merge_timestamp": datetime.now().isoformat(),
                "strategy_used": strategy or self.default_strategy,
                "conflict_count": 0,
                "resolved_conflicts": [],
                "unresolved_conflicts": [],
                "updated_fields": [],
                "merged_fields": len(supplement_result.get("supplement_fields", {}))
            }
            
            # 添加文本补充分析的整体信息
            if "text_supplement" not in merged_result:
                merged_result["text_supplement"] = {
                    "timestamp": datetime.now().isoformat(),
                    "overall_analysis": supplement_result.get("overall_analysis", ""),
                    "parsed_fields_count": supplement_result.get("parsed_fields_count", 0),
                    "high_confidence_fields": supplement_result.get("high_confidence_fields", []),
                    "supplemented_fields": []
                }
            
            # 执行字段合并
            supplement_fields = supplement_result.get("supplement_fields", {})
            for field_name, field_data in supplement_fields.items():
                # 查找对应的编码类目键名
                category_key = self._find_category_key(merged_result, field_name)
                
                if category_key or self._is_custom_field(field_name):
                    # 确定最终使用的字段键名
                    target_key = category_key if category_key else field_name
                    
                    # 检查是否存在冲突
                    conflict_info = self._check_conflict(
                        merged_result["encoding_categories"].get(target_key, {}),
                        field_data,
                        target_key
                    )
                    
                    # 处理合并或冲突
                    if conflict_info["has_conflict"]:
                        merged_result["merger_info"]["conflict_count"] += 1
                        
                        # 选择冲突处理策略
                        resolve_strategy = strategy or self.default_strategy
                        if resolve_strategy not in self.conflict_resolution_strategies:
                            resolve_strategy = self.default_strategy
                        
                        # 执行冲突解决
                        resolution_result = self.conflict_resolution_strategies[resolve_strategy](
                            merged_result["encoding_categories"].get(target_key, {}),
                            field_data,
                            target_key,
                            conflict_info
                        )
                        
                        # 更新结果
                        if resolution_result["resolved"]:
                            merged_result["encoding_categories"][target_key] = resolution_result["resolved_value"]
                            merged_result["merger_info"]["resolved_conflicts"].append(resolution_result)
                            merged_result["merger_info"]["updated_fields"].append(target_key)
                        else:
                            merged_result["merger_info"]["unresolved_conflicts"].append(conflict_info)
                    else:
                        # 无冲突，直接合并
                        self._merge_field(
                            merged_result["encoding_categories"], 
                            target_key, 
                            field_data
                        )
                        merged_result["merger_info"]["updated_fields"].append(target_key)
            
            # 更新视觉结果中的整体置信度
            self._update_overall_confidence(merged_result)
            
            logger.info(f"结果合并完成，处理了 {len(supplement_fields)} 个补充字段，发现 {merged_result['merger_info']['conflict_count']} 个冲突")
            return merged_result
            
        except Exception as e:
            logger.error(f"合并结果时发生错误: {str(e)}")
            # 在原视觉结果中添加错误信息
            if "merger_info" not in vision_result:
                vision_result["merger_info"] = {}
            vision_result["merger_info"]["error"] = str(e)
            vision_result["merger_info"]["merge_timestamp"] = datetime.now().isoformat()
            return vision_result
    
    def _find_category_key(self, vision_result: Dict[str, Any], field_name: str) -> Optional[str]:
        """
        根据字段名称查找对应的编码类目键名
        
        Args:
            vision_result: 视觉分析结果
            field_name: 字段名称
            
        Returns:
            Optional[str]: 找到的类目键名，如果未找到返回None
        """
        encoding_categories = vision_result.get("encoding_categories", {})
        
        # 先尝试直接匹配键名
        if field_name in encoding_categories:
            return field_name
        
        # 尝试通过name字段匹配
        for key, data in encoding_categories.items():
            if isinstance(data, dict) and data.get("name") == field_name:
                return key
        
        # 尝试通过字段名的相似性匹配（例如："视频情感倾向" vs "emotional_tendency"）
        # 预定义的映射关系
        name_mappings = {
            "场景设定": "scene_setting",
            "声音素材": "audio_material",
            "主题类型": "theme_type",
            "视频情感倾向": "emotional_tendency",
            "话题标签": "topic_tags",
            "作者昵称类型": "author_nickname_type",
            "作者简介内容": "author_intro_content"
        }
        
        return name_mappings.get(field_name)
    
    def _is_custom_field(self, field_name: str) -> bool:
        """
        判断是否为自定义字段（非标准编码类目）
        
        Args:
            field_name: 字段名称
            
        Returns:
            bool: 是否为自定义字段
        """
        # 简单判断：如果包含中文字符，可能是自定义字段
        return any('\u4e00'-'\u9fff' in char for char in field_name)
    
    def _check_conflict(self, 
                       current_value: Dict[str, Any], 
                       supplement_value: Dict[str, Any],
                       field_key: str) -> Dict[str, Any]:
        """
        检查是否存在冲突
        
        Args:
            current_value: 当前值（视觉分析结果中的值）
            supplement_value: 补充值（文本补充分析结果中的值）
            field_key: 字段键名
            
        Returns:
            Dict[str, Any]: 冲突信息，包含是否有冲突、当前值、补充值等
        """
        # 如果当前值为空，视为无冲突
        if not current_value:
            return {
                "has_conflict": False,
                "field_key": field_key,
                "current_value": None,
                "supplement_value": supplement_value,
                "conflict_type": None
            }
        
        # 获取当前值和补充值
        current_option = current_value.get("option", "").strip().lower()
        current_confidence = current_value.get("confidence", 0)
        
        supplement_option = supplement_value.get("value", "").strip().lower()
        supplement_confidence = supplement_value.get("confidence", 0)
        
        # 检查值是否不同（忽略大小写和空白字符）
        values_different = current_option != supplement_option and \
                          current_option and supplement_option
        
        if values_different:
            # 判断冲突类型
            if current_confidence >= 70 and supplement_confidence >= 70:
                conflict_type = "high_high_conflict"  # 高置信度冲突
            elif current_confidence >= 70:
                conflict_type = "current_high_conflict"  # 当前值高置信度
            elif supplement_confidence >= 70:
                conflict_type = "supplement_high_conflict"  # 补充值高置信度
            else:
                conflict_type = "low_conflict"  # 低置信度冲突
            
            return {
                "has_conflict": True,
                "field_key": field_key,
                "current_value": current_value,
                "supplement_value": supplement_value,
                "conflict_type": conflict_type,
                "current_option": current_option,
                "supplement_option": supplement_option,
                "current_confidence": current_confidence,
                "supplement_confidence": supplement_confidence
            }
        
        return {
            "has_conflict": False,
            "field_key": field_key,
            "current_value": current_value,
            "supplement_value": supplement_value,
            "conflict_type": None
        }
    
    def _resolve_by_confidence(self, 
                              current_value: Dict[str, Any], 
                              supplement_value: Dict[str, Any],
                              field_key: str,
                              conflict_info: Dict[str, Any]) -> Dict[str, Any]:
        """
        基于置信度的冲突解决策略
        选择置信度较高的值
        
        Args:
            current_value: 当前值
            supplement_value: 补充值
            field_key: 字段键名
            conflict_info: 冲突信息
            
        Returns:
            Dict[str, Any]: 冲突解决结果
        """
        current_confidence = current_value.get("confidence", 0)
        supplement_confidence = supplement_value.get("confidence", 0)
        
        # 置信度差异阈值，小于此值视为无法通过置信度决定
        confidence_threshold = 5
        
        # 如果置信度相同或差异很小，返回未解决
        if abs(current_confidence - supplement_confidence) <= confidence_threshold:
            return {
                "resolved": False,
                "field_key": field_key,
                "reason": "置信度相近，无法通过置信度决定",
                "conflict_info": conflict_info
            }
        
        # 选择置信度较高的值
        if supplement_confidence > current_confidence:
            resolved_value = self._create_merged_field_value(field_key, supplement_value, current_value)
            source = "text_supplement"
            reason = f"文本补充分析置信度更高 ({supplement_confidence} > {current_confidence})"
        else:
            resolved_value = copy.deepcopy(current_value)
            source = resolved_value.get("source", "vision")
            reason = f"当前值置信度更高 ({current_confidence} > {supplement_confidence})"
        
        # 添加冲突解决标记
        resolved_value["conflict_resolved"] = {
            "strategy": "confidence_based",
            "original_value": current_value.get("option"),
            "original_confidence": current_confidence,
            "supplement_value": supplement_value.get("value"),
            "supplement_confidence": supplement_confidence,
            "reason": reason,
            "timestamp": datetime.now().isoformat()
        }
        
        resolved_value["source"] = source
        
        return {
            "resolved": True,
            "field_key": field_key,
            "resolved_value": resolved_value,
            "reason": reason
        }
    
    def _resolve_by_source_priority(self, 
                                   current_value: Dict[str, Any], 
                                   supplement_value: Dict[str, Any],
                                   field_key: str,
                                   conflict_info: Dict[str, Any]) -> Dict[str, Any]:
        """
        基于来源优先级的冲突解决策略
        按照预定义的来源优先级选择值
        
        Args:
            current_value: 当前值
            supplement_value: 补充值
            field_key: 字段键名
            conflict_info: 冲突信息
            
        Returns:
            Dict[str, Any]: 冲突解决结果
        """
        current_source = current_value.get("source", "vision")
        supplement_source = "text_supplement"
        
        # 获取来源优先级
        current_priority = self.source_priorities.get(current_source, 999)
        supplement_priority = self.source_priorities.get(supplement_source, 999)
        
        # 选择优先级更高的值
        if supplement_priority < current_priority:
            resolved_value = self._create_merged_field_value(field_key, supplement_value, current_value)
            reason = f"文本补充分析来源优先级更高 ({supplement_source} > {current_source})"
        else:
            resolved_value = copy.deepcopy(current_value)
            reason = f"当前值来源优先级更高 ({current_source} > {supplement_source})"
        
        # 添加冲突解决标记
        resolved_value["conflict_resolved"] = {
            "strategy": "source_priority",
            "original_value": current_value.get("option"),
            "original_source": current_source,
            "supplement_value": supplement_value.get("value"),
            "supplement_source": supplement_source,
            "reason": reason,
            "timestamp": datetime.now().isoformat()
        }
        
        return {
            "resolved": True,
            "field_key": field_key,
            "resolved_value": resolved_value,
            "reason": reason
        }
    
    def _resolve_by_logging(self, 
                           current_value: Dict[str, Any], 
                           supplement_value: Dict[str, Any],
                           field_key: str,
                           conflict_info: Dict[str, Any]) -> Dict[str, Any]:
        """
        只记录冲突，保留原始值的策略
        
        Args:
            current_value: 当前值
            supplement_value: 补充值
            field_key: 字段键名
            conflict_info: 冲突信息
            
        Returns:
            Dict[str, Any]: 冲突解决结果
        """
        # 添加冲突记录，但保留原始值
        resolved_value = copy.deepcopy(current_value)
        resolved_value["conflict_recorded"] = {
            "strategy": "log_only",
            "supplement_value": supplement_value.get("value"),
            "supplement_confidence": supplement_value.get("confidence"),
            "supplement_reasoning": supplement_value.get("reasoning", ""),
            "timestamp": datetime.now().isoformat()
        }
        
        logger.warning(f"字段 {field_key} 存在冲突，已记录但保留原始值")
        
        return {
            "resolved": True,
            "field_key": field_key,
            "resolved_value": resolved_value,
            "reason": "冲突已记录，但保留原始值"
        }
    
    def _merge_field(self, 
                    target_dict: Dict[str, Any], 
                    field_key: str, 
                    field_data: Dict[str, Any]) -> None:
        """
        合并单个字段
        
        Args:
            target_dict: 目标字典
            field_key: 字段键名
            field_data: 字段数据
        """
        # 如果字段已存在，更新；否则创建新字段
        if field_key in target_dict:
            # 合并现有字段
            existing_field = target_dict[field_key]
            
            # 更新为补充分析的值
            new_field_value = {
                "name": existing_field.get("name", field_key),
                "option": field_data.get("value"),
                "confidence": field_data.get("confidence", 0),
                "source": "text_supplement",
                "reasoning": field_data.get("reasoning", ""),
                "timestamp": datetime.now().isoformat(),
                "merged_at": datetime.now().isoformat()
            }
            
            # 如果原始字段有值，记录原始信息
            if existing_field.get("option"):
                new_field_value["original_option"] = existing_field.get("option")
                new_field_value["original_confidence"] = existing_field.get("confidence")
                new_field_value["original_source"] = existing_field.get("source", "vision")
            
            target_dict[field_key] = new_field_value
        else:
            # 创建新字段
            target_dict[field_key] = {
                "name": field_key,
                "option": field_data.get("value"),
                "confidence": field_data.get("confidence", 0),
                "source": "text_supplement",
                "reasoning": field_data.get("reasoning", ""),
                "timestamp": datetime.now().isoformat(),
                "created_by_supplement": True
            }
    
    def _create_merged_field_value(self, 
                                 field_key: str, 
                                 supplement_value: Dict[str, Any],
                                 current_value: Dict[str, Any]) -> Dict[str, Any]:
        """
        创建合并后的字段值
        
        Args:
            field_key: 字段键名
            supplement_value: 补充值
            current_value: 当前值
            
        Returns:
            Dict[str, Any]: 合并后的字段值
        """
        return {
            "name": current_value.get("name", field_key),
            "option": supplement_value.get("value"),
            "confidence": supplement_value.get("confidence", 0),
            "source": "text_supplement",
            "reasoning": supplement_value.get("reasoning", ""),
            "timestamp": datetime.now().isoformat(),
            "original_option": current_value.get("option"),
            "original_confidence": current_value.get("confidence"),
            "original_source": current_value.get("source", "vision")
        }
    
    def _update_overall_confidence(self, merged_result: Dict[str, Any]) -> None:
        """
        更新合并后的整体置信度
        
        Args:
            merged_result: 合并后的结果
        """
        encoding_categories = merged_result.get("encoding_categories", {})
        confidences = []
        
        # 收集所有置信度值
        for category_data in encoding_categories.values():
            if isinstance(category_data, dict) and "confidence" in category_data:
                confidences.append(category_data["confidence"])
        
        # 计算新的整体置信度
        if confidences:
            new_overall_confidence = int(sum(confidences) / len(confidences))
            merged_result["overall_confidence"] = new_overall_confidence
            
            # 添加置信度变化记录
            if "original_overall_confidence" not in merged_result:
                original_confidence = merged_result.get("overall_confidence", 0)
                merged_result["original_overall_confidence"] = original_confidence
                merged_result["confidence_change"] = new_overall_confidence - original_confidence
    
    def analyze_conflicts(self, merged_result: Dict[str, Any]) -> Dict[str, Any]:
        """
        分析合并结果中的冲突情况
        
        Args:
            merged_result: 合并后的结果
            
        Returns:
            Dict[str, Any]: 冲突分析报告
        """
        merger_info = merged_result.get("merger_info", {})
        
        analysis = {
            "total_conflicts": merger_info.get("conflict_count", 0),
            "resolved_conflicts": len(merger_info.get("resolved_conflicts", [])),
            "unresolved_conflicts": len(merger_info.get("unresolved_conflicts", [])),
            "updated_fields": len(merger_info.get("updated_fields", [])),
            "conflict_types": {},
            "confidence_statistics": {}
        }
        
        # 分析冲突类型分布
        for conflict in merger_info.get("resolved_conflicts", []):
            conflict_type = conflict.get("reason", "unknown")
            analysis["conflict_types"][conflict_type] = analysis["conflict_types"].get(conflict_type, 0) + 1
        
        # 分析置信度统计
        encoding_categories = merged_result.get("encoding_categories", {})
        high_confidence_count = 0
        medium_confidence_count = 0
        low_confidence_count = 0
        
        for category_data in encoding_categories.values():
            if isinstance(category_data, dict) and "confidence" in category_data:
                confidence = category_data["confidence"]
                if confidence >= self.confidence_thresholds["high"]:
                    high_confidence_count += 1
                elif confidence >= self.confidence_thresholds["medium"]:
                    medium_confidence_count += 1
                elif confidence >= self.confidence_thresholds["low"]:
                    low_confidence_count += 1
        
        analysis["confidence_statistics"] = {
            "high_confidence_fields": high_confidence_count,
            "medium_confidence_fields": medium_confidence_count,
            "low_confidence_fields": low_confidence_count,
            "total_fields": len(encoding_categories)
        }
        
        # 添加建议
        analysis["recommendations"] = self._generate_recommendations(analysis, merged_result)
        
        # 更新合并信息
        merged_result["merger_info"]["conflict_analysis"] = analysis
        
        return analysis
    
    def _generate_recommendations(self, analysis: Dict[str, Any], merged_result: Dict[str, Any]) -> List[str]:
        """
        基于冲突分析生成建议
        
        Args:
            analysis: 冲突分析结果
            merged_result: 合并后的结果
            
        Returns:
            List[str]: 建议列表
        """
        recommendations = []
        
        # 检查未解决的冲突
        if analysis["unresolved_conflicts"] > 0:
            recommendations.append("存在未解决的冲突，建议人工审核相关字段")
        
        # 检查低置信度字段
        low_confidence_count = analysis["confidence_statistics"]["low_confidence_fields"]
        if low_confidence_count > 0:
            recommendations.append(f"发现 {low_confidence_count} 个低置信度字段，建议进一步分析")
        
        # 检查整体置信度
        overall_confidence = merged_result.get("overall_confidence", 0)
        if overall_confidence < self.confidence_thresholds["medium"]:
            recommendations.append("整体置信度较低，建议对分析结果进行全面复核")
        elif overall_confidence < self.confidence_thresholds["high"]:
            recommendations.append("整体置信度中等，建议关注高优先级字段的准确性")
        
        return recommendations


# 创建全局结果合并器实例
_result_merger_instance = None

def get_result_merger() -> ResultMerger:
    """
    获取结果合并器实例（单例模式）
    
    Returns:
        ResultMerger: 合并器实例
    """
    global _result_merger_instance
    
    if _result_merger_instance is None:
        _result_merger_instance = ResultMerger()
    
    return _result_merger_instance


if __name__ == "__main__":
    # 测试代码
    print("ResultMerger测试")
    
    # 创建合并器实例
    merger = ResultMerger()
    
    # 模拟视觉分析结果
    vision_result = {
        "status": "success",
        "video_id": "test_video_001",
        "analysis_time": "2023-07-20 10:00:00",
        "overall_confidence": 75,
        "encoding_categories": {
            "scene_setting": {
                "name": "场景设定",
                "option": "校园场景",
                "confidence": 90,
                "source": "vision",
                "timestamp": "2023-07-20 10:00:00"
            },
            "theme_type": {
                "name": "主题类型",
                "option": "教育内容",
                "confidence": 65,
                "source": "vision",
                "timestamp": "2023-07-20 10:00:00"
            },
            "emotional_tendency": {
                "name": "视频情感倾向",
                "option": "中性",
                "confidence": 70,
                "source": "vision",
                "timestamp": "2023-07-20 10:00:00"
            }
        },
        "raw_content": "原始视觉分析内容",
        "fields_to_supplement": ["theme_type", "emotional_tendency"]
    }
    
    # 模拟文本补充分析结果
    supplement_result = {
        "supplement_fields": {
            "主题类型": {
                "value": "学习分享",
                "confidence": 85,
                "reasoning": "根据视频描述和内容关键词分析，视频主要分享学习经验和方法"
            },
            "视频情感倾向": {
                "value": "积极向上",
                "confidence": 90,
                "reasoning": "从语言表达和内容导向来看，视频传递积极向上的情绪"
            },
            "内容标签": {
                "value": "学习方法, 时间管理",
                "confidence": 88,
                "reasoning": "视频中反复提及学习方法和时间管理技巧"
            }
        },
        "overall_analysis": "这是一个关于学习方法分享的积极向上的教育类视频，主要场景在校园。",
        "parsed_fields_count": 3,
        "high_confidence_fields": ["主题类型", "视频情感倾向", "内容标签"]
    }
    
    # 测试不同合并策略
    print("\n1. 测试基于置信度的合并策略：")
    merged_result1 = merger.merge_results(vision_result, supplement_result, strategy="confidence_based")
    print(json.dumps(merged_result1, ensure_ascii=False, indent=2))
    
    print("\n2. 测试基于来源优先级的合并策略：")
    merged_result2 = merger.merge_results(vision_result, supplement_result, strategy="source_priority")
    
    print("\n3. 测试冲突分析：")
    conflict_analysis = merger.analyze_conflicts(merged_result1)
    print(json.dumps(conflict_analysis, ensure_ascii=False, indent=2))
    
    print("\n结果合并器测试完成！")